#include "PSSwitch.h"
//************************************
// Method:    	tRecvBak				从站接收备份线程
// Programmer:  lww
// Time:		2019/2/16
// Returns:   	void *
// Parameter: 	void * arg
//************************************
void *tRecvPSS(void* arg)
{
#define PACK_MAXNUM	6
#define	MAX_JUDGE_NUM 3
#define MEMREAD1(var)	MEMREAD(var, Data2Recv)
#define WRONG_DEAL	{\
	printf("Analyze PSS data wrong!\r\n");\
}
	short status = 0;
	short tmp_short=0;
	short ptr_off;
	int count = 0;
	int sock;
	short Head = 2601;				//< 报头
	short Tail = 3420;				//< 报尾
	char Data2Recv[PACK_MAXNUM] = {};	//< 存放数据包的数组
	short len;
	printf("the Kernel_%s is %d\r\n", "tRecvPSS_ID", syscall(SYS_gettid));			//< duan20200610
	//< 初始化UDP设置
	if (false == UDP_Init(&sock, PSS_PORT, 0, 1000, UDP_RECV_STATUS, NULL)) { return 0; }

	while (1)
	{
		int _iLen = 0;
		ExactDelay(100);
		//< 接收数据
		memset(Data2Recv, 0, sizeof(Data2Recv));
		len = (short)UDP_Recv_Any_Bytes(&sock, Data2Recv, PACK_MAXNUM);
		if (len <= 0) {                     //只要系统启动，但是收不到数据，就切换为主站单独存在
			count++;
			if (count >= MAX_JUDGE_NUM) {
				count = MAX_JUDGE_NUM;
				SYS_Role_Turn(Master_Alone_Role);
			}
		}
		else {
			count = 0;
			//< 校验报头
			memcpy(&tmp_short, (char*)(Data2Recv), sizeof(tmp_short));
			_iLen += sizeof(tmp_short);
			if (tmp_short != Head) { WRONG_DEAL; }

			//< 检验报尾
			memcpy(&tmp_short, (char*)(Data2Recv)+4, sizeof(tmp_short));
			_iLen += sizeof(tmp_short);
			if (tmp_short != Tail) { WRONG_DEAL; }

			//< 接收另一台控制器的状态
			memcpy(&status, (char*)(Data2Recv)+2, sizeof(status));
			_iLen += sizeof(status);

			//判断接收数据的长度是否正确
			if (_iLen != (int)len) { WRONG_DEAL; }

			//如果系统当前身份为未定义，说明此时第一次通讯收到消息，切换为从站
			if (SYS_Role == Default_Role) {
				SYS_Role_Turn(Slave_Role);
				continue;
			}

			//如果系统当前身份为主站单独存在
			else if (SYS_Role == Master_Alone_Role) {

				if (SYS_Status == File_Wait_Status) {//如果系统状态为主站单独存在，等待文件

					if (status == MASTER_RUN) {    //如果收到另一个控制器主站正常运行的消息
						SYS_Role_Turn(Slave_Role);
						continue;
					}
					else if (status == MASTER_WAIT) {//如果收到另一个控制器主站等待文件的消息
						if (IPTail_Num > MASTER_SLAVE_ID_DT) {//此时两个站都是主站且等待文件，16号切为主从，66切为从站
							SYS_Role_Turn(Slave_Role);
							continue;
						}
						else {
							SYS_Role_Turn(Master_Twins_Role);
							continue;
						}
					}
					else if (status == SLAVE_RUN) {//主站等待文件，从站正常运行，此时应切为从站，等下一次循环进入从站状态再进行下一步操作
						SYS_Role_Turn(Slave_Role);
						continue;
					}
					else if (status == SLAVE_WAIT) {//主站单独存在等待文件，从站等待文件，切换为主从
						SYS_Role_Turn(Master_Twins_Role);
						continue;
					}
				}

				else if (SYS_Status == Run_Status) {//如果系统状态为主站单独存在，正常运行

					if (status == MASTER_RUN) {//如果收到另一个控制器主站正常运行的消息
						if (IPTail_Num > MASTER_SLAVE_ID_DT) {//此时两个站都是主站且正常运行，16号切为主从，66切为从站
							SYS_Role_Turn(Slave_Role);
							continue;
						}
						else {
							SYS_Role_Turn(Master_Twins_Role);
							continue;
						}
					}
					else if (status == MASTER_WAIT) {//此时这边系统没问题，切换为主从，另一台控制器应切换为从站等待文件
						SYS_Role_Turn(Master_Twins_Role);
						continue;
					}
					else if (status == SLAVE_RUN) {
						SYS_Role_Turn(Master_Twins_Role);
						continue;
					}
					else if (status == SLAVE_WAIT) {
						SYS_Role_Turn(Master_Twins_Role);
						continue;
					}
				}
			}

			//如果系统当前身份为主从
			else if (SYS_Role == Master_Twins_Role)
			{
				if (SYS_Status == File_Wait_Status) {//如果系统状态为主从，等待文件
					if (status == MASTER_RUN) {    //如果收到另一个控制器主站正常运行的消息
						SYS_Role_Turn(Slave_Role);
						continue;
					}
					else if (status == MASTER_WAIT) {//如果收到另一个控制器主站等待文件的消息
						if (IPTail_Num > MASTER_SLAVE_ID_DT) {//此时两个站都是主站且等待文件，16号切为主从，66切为从站
							SYS_Role_Turn(Slave_Role);
							continue;
						}
						else {
							continue;
						}
					}
					else if (status == SLAVE_RUN) {//主站等待文件，从站正常运行，此时应切为从站，等下一次循环进入从站状态再进行下一步操作
						SYS_Role_Turn(Slave_Role);
						continue;
					}
					else if (status == SLAVE_WAIT) {//主站主从等待文件，从站等待文件
						continue;
					}
				}

				else if (SYS_Status == Run_Status) {//如果系统状态为主站主从，正常运行

					if (status == MASTER_RUN) {//如果收到另一个控制器主站正常运行的消息
						if (IPTail_Num > MASTER_SLAVE_ID_DT) {//此时两个站都是主站且正常运行，16号切为主从，66切为从站
							SYS_Role_Turn(Slave_Role);
							continue;
						}
						else {
							continue;
						}
					}
					else if (status == MASTER_WAIT) {//此时这边系统没问题，切换为主从，另一台控制器应切换为从站等待文件
						continue;
					}
					else if (status == SLAVE_RUN) {
						continue;
					}
					else if (status == SLAVE_WAIT) {
						continue;
					}
				}
			}

			//如果系统当前身份为从站
			else if (SYS_Role == Slave_Role)
			{
				if (SYS_Status == File_Wait_Status) {//如果系统状态为从站，等待文件
					if (status == MASTER_RUN) {    //如果收到另一个控制器主站正常运行的消息
						continue;
					}
					else if (status == MASTER_WAIT) {//如果收到另一个控制器主站等待文件的消息
						continue;
					}
					else if (status == SLAVE_RUN) {//从站等待文件，收到从站正常运行，此时应保持为从站，等下一次循环另一台控制器进入主站状态再进行下一步操作
						continue;
					}
					else if (status == SLAVE_WAIT) {//从站等待文件，从站等待文件
						if (IPTail_Num > MASTER_SLAVE_ID_DT) {//此时两个站都是从站且等待文件，16号切为主从，66切为从站
							continue;
						}
						else {
							SYS_Role_Turn(Master_Twins_Role);
							continue;
						}
					}
				}

				else if (SYS_Status == Run_Status) {//如果系统状态为从站，正常运行

					if (status == MASTER_RUN) {//如果收到另一个控制器主站正常运行的消息
						continue;
					}
					else if (status == MASTER_WAIT) {//从站正常运行，收到主站等待文件，应该切换为主从，另一台切换为从站等待文件
						SYS_Role_Turn(Master_Twins_Role);
						continue;
					}
					else if (status == SLAVE_RUN) {
						if (IPTail_Num > MASTER_SLAVE_ID_DT) {//此时两个站都是从站且正常运行，16号切为主从，66切为从站
							continue;
						}
						else {
							SYS_Role_Turn(Master_Twins_Role);
							continue;
						}
					}
					else if (status == SLAVE_WAIT) {
						SYS_Role_Turn(Master_Twins_Role);
						continue;
					}//Judge Recv
				}//Judge Status
			}//Judge Role
		}//If Recv 
	}//While
	close(sock);//< 断开连接

#undef PACK_MAXNUM
#undef WRONG_DEAL
#undef MEMREAD1
#undef	MAX_JUDGE_NUM
}


//************************************
// Method:    	BakData_PACK_Make			备份文件打包程序
// Programmer:  lww
// Time:		2019/2/16
// Returns:   	int							打包长度
// Parameter: 	void * Data					数据包头指针
// Parameter: 	short Head					报头
// Parameter: 	short Tail					报尾
// Parameter: 	int Limit_Len				单次数据包长度限制
// Parameter: 	short * SaveModel_Num		存储的模块的数量
//************************************
int PSS_PACK_Make(void* Data, short Head, short Tail, short* SaveModel_Num)
{
#define MEMWRITE1(name)	MEMWRITE(name, Data);
	int _iLen = 0;
	//< 报头
	MEMWRITE1(Head);
	//< 信息量
	MEMWRITE1(SaveModel_Num[0]);
	//< 报尾
	MEMWRITE1(Tail);
	return _iLen;
#undef MEMWRITE1
}


//************************************
// Method:    	tPSSwitch				主站或从站状态发送+主从站身份判断线程
// Programmer:  lww
// Time:		2019/2/16
// Returns:   	void *
// Parameter: 	void * arg
//************************************
void *tPSSwitch(void* arg)
{
#define PACK_MAXNUM	6
	int sock;
	struct sockaddr_in NetC;
	struct timespec time;
	short Head = 2601;				//< 报头
	short Tail = 3420;				//< 报尾
	char Data2Send[PACK_MAXNUM];	//< 存放数据包的数组
	int _iLen = 0;
	short SendStatus =0; //要发送的主站或从站状态
	pthread_t tPSS_ID = 0;
	//< 初始化UDP设置
	if (false == UDP_Init(&sock, PSS_PORT, 0, 1000, UDP_SEND_STATUS, nullptr)) { return 0; }

	//< 开启接收备份数据的线程
	THREAD_CREATE_FAILED(Thread_Create("tRecvPSS_ID", &tPSS_ID, NULL, SCHED_POLICY, 89, true, tRecvPSS, CONTROL_CORE, NULL));

	//< 设置发送到的IP地址及端口
	Addr_Set(&NetC, PSS_PORT, inet_addr(NETD_PSS_BC));
	while (1)
	{
		ExactDelay(100);
		if((SYS_Role == Master_Twins_Role||SYS_Role== Master_Alone_Role)){
			if (SYS_Status == Run_Status) {
				SendStatus = MASTER_RUN;
			}
			else if (SYS_Status == File_Wait_Status){
				SendStatus = MASTER_WAIT;
			}

		}
		else if (SYS_Role==Slave_Role){
			if (SYS_Status == Run_Status) {
				SendStatus = SLAVE_RUN;
			}
			else if (SYS_Status == File_Wait_Status) {
				SendStatus = SLAVE_WAIT;
			}
		}

		if (SendStatus!=0){
			_iLen = PSS_PACK_Make(Data2Send, Head, Tail, &SendStatus);  //发送了主站或从站状态
			if (-1 == UDP_Send(&sock, &NetC, (char*)Data2Send, _iLen))
				continue;
		}

	}
	close(sock);//< 断开连接
#undef PACK_MAXNUM

}
